home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / xcoral / xcoral.lha / xcoral-1.72 / get_string.c < prev    next >
C/C++ Source or Header  |  1993-02-19  |  12KB  |  439 lines

  1. /*
  2. ** Copyright 1989, 1992 by Lionel Fournigault
  3. **
  4. ** Permission to use, copy, and distribute for non-commercial purposes,
  5. ** is hereby granted without fee, providing that the above copyright
  6. ** notice appear in all copies and that both the copyright notice and this
  7. ** permission notice appear in supporting documentation.
  8. ** The software may be modified for your own purposes, but modified versions
  9. ** may not be distributed.
  10. ** This software is provided "as is" without any expressed or implied warranty.
  11. **
  12. **
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <X11/Xlib.h>
  17. #include <X11/cursorfont.h>
  18. #include <X11/Xutil.h>
  19. #include <X11/keysym.h>
  20. #include <ctype.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <string.h>
  24. #include <pwd.h>
  25.  
  26. #include "options.h"
  27. #include "flist.h"
  28.  
  29. #define D_WIDTH        10
  30. #define D_HEIGHT    10
  31. #define D_SHADOW    6
  32. #define D_WARNING    0
  33. #define D_DIALOG    1
  34. #define D_MESSAGE    2
  35. #define DS_OK        "  Ok...  "
  36. #define DS_DIALOG    "Dialog Box"
  37. #define DS_CANCEL    "Cancel"
  38.  
  39. typedef struct {
  40.     Window        frame, shadow, title, main, ok, cancel;
  41.     unsigned long     fg, bg, ts, bs;
  42.     GC        gc;
  43.     XFontStruct     *font;
  44.     int        t_height, b_width;
  45.     int        width, height;
  46. } Dialog;
  47.  
  48. Dialog dial;
  49.  
  50. extern Display    *dpy;
  51. extern char     *getenv ();
  52. char         *GetStringFromWindow ();
  53. char        *ExpandTildeName ();
  54.  
  55.  
  56. /*
  57. **    Function name : InitDialogWindow
  58. **
  59. **    Description : Initialisation de la fenetre de dialog,
  60. **        la fonte, les couleurs etc...
  61. **    Input : 
  62. **    Ouput :
  63. */
  64. void InitDialogWindow ()
  65. {
  66.     XWindowAttributes att;
  67.         Window root;
  68.         int screen;
  69.     unsigned long black, white;
  70.     XGCValues     gcv;
  71.     XSizeHints sizehints;
  72.  
  73.     black = BlackPixel ( dpy, DefaultScreen ( dpy ));
  74.     white = WhitePixel ( dpy, DefaultScreen ( dpy ));
  75.  
  76.     dial.fg = (DefaultDepth ( dpy, DefaultScreen ( dpy )) == 1) ? 
  77.         black : GetOpColor ( OP_MENU_FG );
  78.     dial.bg = (DefaultDepth ( dpy, DefaultScreen ( dpy )) == 1) ?
  79.         white : GetOpColor ( OP_MENU_BG );
  80.     dial.ts = GetOpColor ( OP_MENU_TS );
  81.     dial.bs = GetOpColor ( OP_MENU_BS );
  82.     dial.font = GetOpFont ( OP_TEXT_FONT );
  83.  
  84.     dial.gc = XCreateGC ( dpy, DefaultRootWindow ( dpy ), 0,  &gcv );
  85.      XCopyGC ( dpy, DefaultGC (dpy, DefaultScreen ( dpy )), (~0), dial.gc );
  86.  
  87.     XSetFont ( dpy, dial.gc, dial.font -> fid );
  88.     XSetForeground ( dpy, dial.gc, dial.fg );
  89.     XSetBackground ( dpy, dial.gc, dial.bg );
  90.  
  91.     screen = DefaultScreen ( dpy );
  92.     root = RootWindow ( dpy, screen );
  93.     XGetWindowAttributes ( dpy, root, &att );
  94.     dial.width = att.width / 2;
  95.     dial.height = att.height / 5 ;
  96.  
  97.     dial.frame = XCreateSimpleWindow ( dpy, root, 
  98.         ((att.width/2) - (dial.width/2)),((att.height/2) - (dial.height/2)),
  99.         dial.width, dial.height, 0, black, black );
  100.  
  101.     dial.t_height = dial.font -> ascent + dial.font -> descent + 10;
  102.     dial.title = XCreateSimpleWindow ( dpy,    dial.frame, 0, 0,
  103.         dial.width, dial.t_height, 0, dial.fg, dial.bg);
  104.  
  105.     dial.main = XCreateSimpleWindow ( dpy, dial.frame, 0, dial.t_height,
  106.         dial.width, dial.height - dial.t_height, 0, dial.fg, dial.bg);
  107.  
  108.     dial.b_width = XTextWidth ( dial.font, DS_OK,  strlen (DS_OK)) + 10;
  109.  
  110.     dial.ok = XCreateSimpleWindow ( dpy, dial.main, (dial.width/2) - (2*dial.b_width),
  111.         dial.height/3, dial.b_width, dial.t_height, 0, dial.fg, dial.bg );
  112.     
  113.     dial.cancel = XCreateSimpleWindow ( dpy, dial.main, (dial.width/2) + dial.b_width,
  114.         dial.height/3, dial.b_width, dial.t_height, 0, dial.fg, dial.bg );
  115.  
  116.     sizehints.flags = PPosition | PSize | USPosition | USSize ;
  117.     sizehints.height = dial.height;
  118.     sizehints.width = dial.width;
  119.     sizehints.x = ((att.width/2) - (dial.width/2));
  120.     sizehints.y = ((att.height/2) - (dial.height/2));
  121.  
  122.     XSetWMProperties ( dpy, dial.frame, 0, 0, 0, 0, &sizehints, 0, 0 );
  123.     
  124.     XSelectInput ( dpy, dial.main, ExposureMask | KeyPressMask );
  125.     XSelectInput ( dpy, dial.title, ExposureMask );
  126.     XSelectInput ( dpy, dial.cancel, ButtonPressMask |ButtonReleaseMask | ExposureMask);
  127.     XSelectInput ( dpy, dial.ok, ButtonPressMask |ButtonReleaseMask | ExposureMask );
  128. }
  129.  
  130.  
  131. /*
  132. **    Function name : GetStringFromDialogBox
  133. **
  134. **    Description : Ouvre une fenetre de dialog (grabbee),
  135. **        et manage les differentes actions possibles
  136. **        pour l'utilisaterur. Clavier et bouttons.
  137. **
  138. **    Input : La fenetre parent, le prompt.
  139. **    Ouput : La chaine.
  140. */
  141. char *GetStringFromDialogBox ( w, s )
  142.     Window    w;
  143.     char     *s;
  144. {
  145.     register int x;
  146.     XEvent event;
  147.     register char *str;
  148.     register int type;
  149.  
  150.     if ( strncmp ( s, "Warning", 7 ) == 0 )
  151.         type = D_WARNING;
  152.     else if ( strncmp ( s, "Message", 7 ) == 0 )
  153.         type = D_MESSAGE;
  154.     else
  155.         type = D_DIALOG;
  156.     
  157.     XMapSubwindows (dpy, dial.main );
  158.     XMapWindow ( dpy, dial.main );
  159.     XMapSubwindows ( dpy, dial.frame);
  160.     XMapRaised ( dpy, dial.frame);
  161.     XWindowEvent ( dpy, dial.main, ExposureMask, &event );
  162.  
  163.     if ( (type != D_WARNING) && (type != D_MESSAGE) ) 
  164.         XWindowEvent ( dpy, dial.cancel, ExposureMask, &event );
  165.     else 
  166.         XUnmapWindow ( dpy, dial.cancel );
  167.  
  168.     Display3D ( dpy, dial.title, dial.ts, dial.bs, 1, 0 );
  169.     Display3D ( dpy, dial.main, dial.ts, dial.bs, 1, 0 );
  170.     Display3D ( dpy, dial.ok, dial.ts, dial.bs, 1, 0 );
  171.     if ( (type != D_WARNING) && (type != D_MESSAGE) )
  172.         Display3D ( dpy, dial.cancel, dial.ts, dial.bs, 1, 0 );
  173.  
  174.     x = XTextWidth ( dial.font, DS_DIALOG, strlen (DS_DIALOG));
  175.     XDrawString ( dpy, dial.title, dial.gc, (dial.width - x)/2,
  176.         dial.font -> ascent + 5, DS_DIALOG, strlen (DS_DIALOG) );
  177.     x = XTextWidth ( dial.font, DS_OK, strlen(DS_OK));
  178.     XDrawString ( dpy, dial.ok, dial.gc, (dial.b_width - x)/2,
  179.         dial.font -> ascent + 5, DS_OK, strlen(DS_OK));
  180.     x = XTextWidth ( dial.font, DS_CANCEL, strlen (DS_CANCEL));
  181.     if ( (type != D_WARNING) && (type != D_MESSAGE) )
  182.         XDrawString ( dpy, dial.cancel, dial.gc,
  183.         (dial.b_width - x)/2, dial.font -> ascent + 5,
  184.         DS_CANCEL, strlen (DS_CANCEL));
  185.  
  186.      str = GetStringFromWindow ( dial.main, dial.gc, dial.font,
  187.         s, 20, dial.font -> ascent + 20 , (char *) 0, 1 );
  188.  
  189.     XUnmapSubwindows ( dpy, dial.main );
  190.     XUnmapWindow ( dpy, dial.main );
  191.     XUnmapSubwindows ( dpy, dial.frame );
  192.     XUnmapWindow ( dpy, dial.frame );
  193.  
  194.     return str;
  195. }
  196.  
  197.  
  198. /*
  199. **    Function name : GetStrinFromWindow
  200. **
  201. **    Description : Assure toute la gestion concernant
  202. **        l'entree d'une chaine de caracteres.
  203. **    Input : La fenetre, le contexte graphique, la fonte,
  204. **        le prompt, la position de depart, le type de
  205. **        reponse ( chaine complete, ou un seul caractere )
  206. **        et un flag pour savoir si on doit tenir compte 
  207. **        des 'ButtonPress'.
  208. **        
  209. **    Ouput : La chaine.
  210. */
  211. char *GetStringFromWindow ( w, gc, font, s, x, y, reply, flag )
  212.     Window        w;
  213.     GC        gc;
  214.     XFontStruct    *font;
  215.     register char     *s;
  216.     register int     x, y;
  217.     register char     *reply;
  218.     register int     flag;
  219. {
  220.     XEvent         event;
  221.     register int     length, cur_x, cur_x_old;
  222.     XComposeStatus     compose;
  223.     KeySym        keysym;
  224.     register int     start_x, max, font_h;
  225.     XWindowAttributes att;
  226.     register int type;
  227.         Window root, parent, **child;
  228.         unsigned int nchild;
  229.     
  230. #define MAXLENGTH     256
  231. #define VOLUME        10
  232.     static char string [MAXLENGTH];
  233.     static char buffer [MAXLENGTH];
  234.  
  235.     if ( strncmp ( s, "Warning", 7 ) == 0 )
  236.         type = D_WARNING;
  237.     else if ( strncmp ( s, "Message", 7 ) == 0 )
  238.         type = D_MESSAGE;
  239.     else
  240.         type = D_DIALOG;
  241.     XGetWindowAttributes ( dpy, w, &att );
  242.  
  243.     XQueryTree ( dpy, w, &root, &parent, (Window **) &child, &nchild );
  244.  
  245.     if ( nchild == 0 ) 
  246.         XGrabPointer ( dpy, w, True, ButtonPress, GrabModeAsync,
  247.             GrabModeAsync, None, None, CurrentTime ); 
  248.     else 
  249.         XGrabPointer ( dpy, w, True, ButtonPress, GrabModeAsync,
  250.             GrabModeAsync, w, None, CurrentTime );
  251.  
  252.     if ( child != 0 )
  253.         XFree ( (char *) child );
  254.  
  255.     XFlush (dpy );
  256.     max = att.width - 40;
  257.     font_h = font -> ascent + font -> descent;
  258.     if ( type == D_MESSAGE ) s += strlen ( "Message : " );
  259.     XDrawImageString ( dpy, w, gc, x, y, s, strlen (s) );
  260.     if ( type == D_DIALOG ) {
  261.         start_x = x + XTextWidth ( font, s, strlen (s) );
  262.         XFillRectangle ( dpy, w, gc, start_x, y - font -> ascent,  font_h/2, font_h );
  263.     }
  264.     cur_x = start_x;
  265.     string [0] = buffer [0] = buffer [1] = '\0';
  266.     for (;;) {
  267.         XNextEvent ( dpy, &event );
  268.         switch ( event.type ) {
  269.         case ButtonPress :
  270.             if ( flag == 0 ) continue;
  271.             if ( event.xbutton.window == dial.ok ) {
  272.                 Display3D ( dpy, dial.ok, dial.ts, dial.bs, 1, 1 );
  273.                 WaitButtonRelease ( event.xbutton.button );
  274.                 if ( strlen(string) )
  275.                     if ( string [0] != '~' )
  276.                         return string;
  277.                     else
  278.                         return ( (char *) ExpandTildeName ( string ));
  279.                 else
  280.                     return 0;
  281.             }
  282.             if ( event.xbutton.window == dial.cancel ) {
  283.                 Display3D ( dpy, dial.cancel, dial.ts, dial.bs, 1, 1 );
  284.                 WaitButtonRelease ( event.xbutton.button );
  285.                 string [0] = '\007';
  286.                 string [1] = '\0';
  287.                 return string;
  288.             }
  289.             break;
  290.         case KeyPress:
  291.             if ( (type == D_WARNING) || (type == D_MESSAGE) )
  292.                 continue;
  293.             XLookupString ( (XKeyEvent *) &event.xkey, buffer,MAXLENGTH, 
  294.                     &keysym, &compose );
  295.              /* Cas return, linefeed ou enter */
  296.             if ( (keysym == XK_Return) || (keysym == XK_KP_Enter)
  297.                 || (keysym == XK_Linefeed) ) {
  298.                 XClearArea( dpy, w, x,
  299.                        y - font -> ascent,
  300.                        XTextWidth ( font, string,
  301.                                strlen ( string )) +
  302.                        XTextWidth ( font, s, strlen (s)) + font_h/2, font_h, False );
  303.                 XUngrabPointer ( dpy, CurrentTime );
  304.                 if ( reply != 0 ) {
  305.                     (void) strncat ( string, "\n", 1 );
  306.                     return string;
  307.                 }
  308.                 if ( strlen ( string ))
  309.                     if ( string [0] != '~' )
  310.                         return string;
  311.                     else
  312.                         return ( (char *) ExpandTildeName ( string ));
  313.                 else 
  314.                     return 0;
  315.             }
  316.             /* Cas du Controle G */
  317.             else if ( (keysym == XK_Control_L) ||
  318.                   (keysym == XK_Control_R)) {
  319.                   continue;
  320.                   /* on ne fait rien */
  321.             }
  322.             else if ( keysym == XK_g  && event.xkey.state == ControlMask ) { 
  323.                 XUngrabPointer ( dpy, CurrentTime ); 
  324.                 string [0] = '\007';
  325.                 string [1] = '\0';
  326.                 return string;
  327.             }
  328.             /* Cas des caracteres imprimables */
  329.             else if ( ( (keysym >= XK_KP_Space)
  330.                     && (keysym <= XK_KP_9) )
  331.                   || ( (keysym >= XK_space)
  332.                          && (keysym <= XK_asciitilde) ) ) {
  333.                 if ( reply != 0 ) {
  334.                     XUngrabPointer ( dpy, CurrentTime );
  335.                            (void) strncat ( string, buffer, 1 );
  336.                            string [1] = '\0';
  337.                            return string;
  338.                 }
  339.                 if ( (strlen(string) + strlen(buffer))
  340.                     >= MAXLENGTH 
  341.                     || XTextWidth ( font, s, strlen (s))
  342.                         + XTextWidth ( font, string,
  343.                         strlen (string)) > max ) {
  344.                             XBell ( dpy, VOLUME );
  345.                             continue;
  346.                               }
  347.                 else {
  348.                     (void) strncat ( string, buffer, 1 );
  349.                       }
  350.             }
  351.             /* Cas shift */
  352.             else if ( (keysym >= XK_Shift_L )
  353.                   && (keysym <= XK_Shift_R) ) {
  354.                   /* On fait rien */
  355.                     continue;
  356.             }
  357.             /* Cas des fonctions speciales */
  358.             else if ( (keysym >= XK_F1) && (keysym <= XK_F35) ) {
  359.                 if ( buffer == 0 )
  360.                     (void) fprintf ( stderr, "Umapped function key\n" );
  361.                 /* on ne fait rien */
  362.                 else if ( (strlen(string) + strlen(buffer)) >= MAXLENGTH ) 
  363.                     XBell ( dpy, VOLUME );
  364.                 else {
  365.                     XBell ( dpy, VOLUME );
  366.                     continue;
  367.                 }
  368.             }
  369.  
  370.             /* Cas delete et backspace. */
  371.             else if ( (keysym == XK_BackSpace) || (keysym ==XK_Delete) ) {
  372.                 if ( (length = strlen(string)) > 0 ) {
  373.                     string [ length - 1 ] = 0;
  374.                     cur_x_old = cur_x;
  375.                     cur_x = start_x + 
  376.                         XTextWidth ( font, string, strlen (string));
  377.                     XClearArea( dpy, w, cur_x, y - font -> ascent,
  378.                            (font_h / 2) + (cur_x_old - cur_x),
  379.                            font_h, False );
  380.  
  381.                     XFillRectangle ( dpy, w, gc, cur_x, y - font -> ascent, 
  382.                         font_h/2, font_h );
  383.                 }
  384.                 else
  385.                     XBell ( dpy, VOLUME );
  386.                 continue;
  387.             }
  388.             else {
  389.                 XBell ( dpy, VOLUME );
  390.                 continue;
  391.             }
  392.  
  393.             XDrawImageString ( dpy, w, gc, cur_x, y, buffer, 1 );
  394.             cur_x_old = cur_x;
  395.             cur_x += XTextWidth ( font, buffer, 1 );
  396.             XFillRectangle ( dpy, w, gc, cur_x, y - font -> ascent,  font_h/2, font_h );
  397.             break;
  398.         }
  399.     }
  400. }
  401.  
  402.  
  403. /*
  404. **    Function name : ExpandTildeName
  405. **
  406. **    Description : Recherche le path de l'expression ~[name]
  407. **    Input : ~/, ~name 
  408. **    Ouput : Le path
  409. */
  410. char *ExpandTildeName ( name )
  411.     register char *name;
  412. {
  413.     register struct passwd *pwd;
  414.     register char *home;
  415.     register char *p = name + 1;
  416.     static char  buf [256];
  417.  
  418.     bzero ( buf, 128 );
  419.     if ( name [1] == '/' ) {    /* c'est moi */
  420.         if ( (home = (char *) getenv ( "HOME" )) == 0 )
  421.             return name;
  422.         (void) strcpy ( buf, home );
  423.         (void) strcat ( buf, name + 1 );
  424.     }
  425.     else { /* c'est un autre */
  426.         while ( *p && *p != '/' ) p++;
  427.         *p = 0;
  428.         pwd = getpwnam ( name + 1 );
  429.         if (  pwd ) {
  430.             (void) strcpy ( buf, pwd ->  pw_dir);
  431.             *p = '/';
  432.             (void) strcat ( buf, p );
  433.         }
  434.         else
  435.             return name;
  436.     }
  437.     return buf;
  438. }
  439.